home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / executor / ex_scan.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  11.1 KB  |  375 lines

  1. /* ----------------------------------------------------------------
  2.  *   FILE
  3.  *    ex_scan.c
  4.  *    
  5.  *   DESCRIPTION
  6.  *    This code provides support for generalized relation scans.
  7.  *    ExecScan is passed a node and a pointer to a function to
  8.  *    "do the right thing" and return a tuple from the relation.
  9.  *    ExecScan then does the tedious stuff - checking the
  10.  *    qualification and projecting the tuple appropriately.
  11.  *
  12.  *   INTERFACE ROUTINES
  13.  *       ExecScan
  14.  *
  15.  *   NOTES
  16.  *    
  17.  *   IDENTIFICATION
  18.  *    $Header: /private/postgres/src/executor/RCS/ex_scan.c,v 1.4 1992/07/01 04:57:33 mer Exp $
  19.  * ----------------------------------------------------------------
  20.  */
  21.  
  22. /* ----------------
  23.  *    FILE INCLUDE ORDER GUIDELINES
  24.  *
  25.  *    1) execdebug.h
  26.  *    2) various support files ("everything else")
  27.  *    3) node files
  28.  *    4) catalog/ files
  29.  *    5) execdefs.h and execmisc.h
  30.  *    6) externs.h comes last
  31.  * ----------------
  32.  */
  33.  
  34. #include <sys/file.h>
  35. #include "executor/executor.h"
  36.  
  37.  RcsId("$Header: /private/postgres/src/executor/RCS/ex_scan.c,v 1.4 1992/07/01 04:57:33 mer Exp $");
  38. /* ----------------------------------------------------------------
  39.  *       ExecScan
  40.  *   
  41.  *       Scans the relation using the 'access method' indicated and 
  42.  *       returns the next qualifying tuple in the direction specified
  43.  *       in the global variable ExecDirection.
  44.  *       The access method returns the next tuple and execScan() is 
  45.  *       responisble for checking the tuple returned against the qual-clause.
  46.  *       
  47.  *       If the tuple retrieved contains locks set by rules, the tuple is 
  48.  *       passed to the Tuple Rule Manager and the rule descriptor returned 
  49.  *       is kept. Also, a flag is set (set_ss_RuleFlag) so that subsequent 
  50.  *       calls know that a rule is activated and the Tuple Rule Manager 
  51.  *       is called to return any possible tuple formed from the set of rules.
  52.  *       The flag is cleared if the Tuple Rule Manager fails to return any
  53.  *       tuple and the relation is scanned instead to retrieve the next tuple.
  54.  *   
  55.  *   
  56.  *       Conditions:
  57.  *         -- the "cursor" maintained by the AMI is positioned at the tuple
  58.  *            returned previously.
  59.  *   
  60.  *       Initial States:
  61.  *         -- the relation indicated is opened for scanning so that the 
  62.  *            "cursor" is positioned before the first qualifying tuple.
  63.  *         -- state variable ruleFlag = nil.
  64.  *
  65.  *    May need to put startmmgr  and endmmgr in here.
  66.  * ----------------------------------------------------------------
  67.  */
  68. /**** xxref:
  69.  *           ExecInitScanAttributes
  70.  *           ExecIndexScan
  71.  *           ExecSeqScan
  72.  ****/
  73. TupleTableSlot
  74. ExecScan(node, accessMtd)
  75.     Scan    node;
  76.     Pointer (*accessMtd)();    /* function returning a tuple */
  77. {
  78.     ScanState        scanstate;
  79.     EState        estate;
  80.     List        qual;
  81.     bool        qualResult;
  82.     List        targetList;
  83.     int            len;
  84.     TupleDescriptor    tupType;
  85.     Pointer        tupValue;
  86.     Relation        scanRelation;
  87.     Index        scanRelid;
  88.     AttributeNumberPtr    scanAtts;
  89.     int            scanNumAtts;
  90.     int            i;
  91.     bool        isDone;
  92.     bool        madeBogusScanAtts = false;
  93.     
  94.     TupleTableSlot    slot;
  95.     TupleTableSlot    resultSlot;
  96.     HeapTuple         newTuple;
  97.     HeapTuple        changedTuple;
  98.     HeapTuple        viewTuple;
  99.  
  100.     int            status;
  101.     ItemPointer        tuple_tid;
  102.     Index        oldRelId;
  103.     RelationInfo    resultRelationInfo;
  104.     Index        resultRelationIndex;
  105.     Prs2EStateInfo    prs2EStateInfo;
  106.     RelationRuleInfo    relRuleInfo;
  107.     ExprContext        econtext;
  108.     ProjectionInfo    projInfo;
  109.     
  110.     scanstate =         get_scanstate(node);
  111.     
  112.     /* ----------------
  113.      *    initialize misc variables
  114.      * ----------------
  115.      */
  116.     newTuple =     NULL;
  117.     slot =    NULL;
  118.     
  119.     estate =     (EState) get_state((Plan) node);
  120.     
  121.     /* ----------------
  122.      *    get the expression context
  123.      * ----------------
  124.      */
  125.     econtext =         get_cs_ExprContext((CommonState) scanstate);
  126.     prs2EStateInfo =     get_es_prs2_info(estate);
  127.     relRuleInfo =     get_css_ruleInfo((CommonScanState) scanstate);
  128.     
  129.     /* ----------------
  130.      *    initialize fields in ExprContext which don't change
  131.      *    in the course of the scan..
  132.      * ----------------
  133.      */
  134.     qual =         get_qpqual((Plan) node);
  135.     scanRelation =    get_css_currentRelation((CommonScanState) scanstate);
  136.     scanRelid =        get_scanrelid(node);
  137.  
  138.     set_ecxt_relation(econtext, scanRelation);
  139.     set_ecxt_relid(econtext, scanRelid);
  140.         
  141.     if (get_cs_TupFromTlist((CommonState)scanstate)) {
  142.     projInfo = get_cs_ProjInfo((CommonState)scanstate);
  143.     resultSlot = ExecProject(projInfo, &isDone);
  144.     if (!isDone)
  145.         return resultSlot;
  146.     }
  147.     /* ----------------
  148.      *    get a tuple from the access method and have the
  149.      *  rule manager process it..  loop until we obtain
  150.      *  a tuple which passes the qualification.
  151.      * ----------------
  152.      */
  153.     for(;;) {
  154.     /* ----------------
  155.      * First check to see if we have 'view' rules.
  156.      * If yes, proccess all the tuples returned by them before
  157.      * you process any of the "real" tuples (the ones returned
  158.      * by the access method).
  159.      *
  160.      * NOTE: If this is a parent of another node (e.g. sort)
  161.      * and not an actual relation scan, then RelationRuleInfo == NULL!
  162.      * ----------------
  163.      */
  164.     if (relRuleInfo != NULL &&
  165.         prs2MustCallRuleManager(relRuleInfo, (HeapTuple) NULL,
  166.                     InvalidBuffer, RETRIEVE))
  167.     {
  168.         viewTuple = prs2GetOneTupleFromViewRules(
  169.                 relRuleInfo,
  170.                 prs2EStateInfo,
  171.                 scanRelation,
  172.                 get_es_explain_relation(estate));
  173.         
  174.         /* ----------------
  175.          * note that the data pointed by 'relRuleInfo'
  176.          * might change, but as 'relRuleInfo' is a pointer,
  177.          * there is no need to do a 
  178.          *     set_css_ruleInfo(scanState, relRuleInfo);
  179.          * ----------------
  180.          */
  181.         if (viewTuple != NULL) {
  182.         /* ----------------
  183.          * We've found a 'view' tuple
  184.          * ----------------
  185.          */
  186.         ExecStoreTuple((Pointer)viewTuple,
  187.                    (Pointer)
  188.                    get_css_ScanTupleSlot((CommonScanState)
  189.                              scanstate),
  190.                    InvalidBuffer,
  191.                    true);
  192.         
  193.         } else if (relRuleInfo->insteadViewRuleFound) {
  194.         /* ----------------
  195.          * No more view rules, but (at least) one of them,
  196.          * was an "instead" rule. So, do not call the access method
  197.          * for more tuples, and pretend that that was the end
  198.          * of the scan
  199.          * ----------------
  200.          */
  201.         return (TupleTableSlot)
  202.             ExecClearTuple((Pointer) 
  203.                    get_css_ScanTupleSlot((CommonScanState)
  204.                              scanstate));
  205.         
  206.         } else {
  207.         /* ----------------
  208.          * No more view rules and no instead rule found.
  209.          * Put clear the ScanTupleSlot to show that...
  210.          * ----------------
  211.          */
  212.         ExecClearTuple((Pointer)
  213.                    get_css_ScanTupleSlot((CommonScanState)
  214.                              scanstate));
  215.         }
  216.     } else {
  217.         /*
  218.          * RelationRuleInfo == NULL, so there are no rules...
  219.          */
  220.         ExecClearTuple((Pointer)
  221.                get_css_ScanTupleSlot((CommonScanState)scanstate));
  222.     }
  223.  
  224.     if (TupIsNull((Pointer)
  225.               get_css_ScanTupleSlot((CommonScanState)scanstate))) {
  226.         /* ----------------
  227.          * No (more) rules and no "instead" rules....
  228.          * Call the access method for more tuples...
  229.          * ----------------
  230.          */
  231.         slot = (TupleTableSlot) (*accessMtd)(node);
  232.         
  233.         /* ----------------
  234.          *  if the slot returned by the accessMtd contains
  235.          *  NULL, then it means there is nothing more to scan
  236.          *  so we just return the empty slot.
  237.          * ----------------
  238.          */
  239.         if (TupIsNull((Pointer) slot))
  240.         return slot;
  241.         
  242.     } else {
  243.         /* ----------------
  244.          * use the "view" tuple
  245.          * ----------------
  246.          */
  247.         slot = (TupleTableSlot) get_css_ScanTupleSlot((CommonScanState)
  248.                               scanstate);
  249.     }
  250.     
  251.     /*
  252.      * call the rule manager only if necessary...
  253.      */
  254.     if (relRuleInfo != NULL &&
  255.         prs2MustCallRuleManager(relRuleInfo,
  256.                     (HeapTuple) ExecFetchTuple((Pointer) slot),
  257.                     ExecSlotBuffer((Pointer) slot),
  258.                     RETRIEVE))
  259.     {
  260.  
  261.         /* ----------------
  262.          *  get the attribute information about the tuple
  263.          * ----------------
  264.          */
  265.         scanNumAtts =    get_cs_NumScanAttributes((CommonState) scanstate);
  266.         scanAtts =    get_cs_ScanAttributes((CommonState) scanstate);
  267.  
  268.         /* ----------------
  269.          *  if the system didn't precalculate the scan attribute
  270.          *  information (which is the right thing), then we generate
  271.          *  a list of all the attributes.  This means the rule manager
  272.          *  does much more work than it should because our current
  273.          *  interface is lame.  -cim 3/15/90
  274.          * ----------------
  275.          */
  276.         if (scanAtts == NULL) {
  277.         scanNumAtts = ((HeapTuple)
  278.                    ExecFetchTuple((Pointer) slot))->t_natts;
  279.         scanAtts = ExecMakeBogusScanAttributes(scanNumAtts);
  280.         madeBogusScanAtts = true;
  281.         }
  282.         
  283.         /* ----------------
  284.          *  have the rule manager process the tuple
  285.          *  if it returns a new tuple, then we use the
  286.          *  tuple it returns in place of our original tuple
  287.          *
  288.          *  XXX the current rule manager interface only allows
  289.          *      the rule system to return one tuple per scan tuple.
  290.          *      This will have to change so that a single scan tuple
  291.          *      will return many tuples by calling prs2Main repeatedly.
  292.          *      -cim 3/15/90
  293.          * ----------------
  294.          */
  295.     
  296.         status = prs2Main(estate,
  297.                   relRuleInfo,
  298.                   RETRIEVE,             /* operation */
  299.                   0,                 /* userid */
  300.                   scanRelation,            /* base rel */
  301.                   (HeapTuple) ExecFetchTuple((Pointer) slot)
  302.                   , /* tuple */
  303.                   ExecSlotBuffer((Pointer) slot),     /* tuple's buffer */
  304.                   NULL,            /* update tuple */
  305.                   InvalidBuffer,    /* update tuple buffer */
  306.                   (HeapTuple) NULL,    /* 'raw' tuple */
  307.                   InvalidBuffer,
  308.                   scanAtts,        /* atts of interest */
  309.                   scanNumAtts,     /* number of atts */
  310.                   &changedTuple,    /* return: tuple */
  311.                   NULL);        /* return: buffer */
  312.         
  313.         /*
  314.          * pfree the bogus scan atts.
  315.          */
  316.         if (madeBogusScanAtts)
  317.         ExecFreeScanAttributes(scanAtts);
  318.  
  319.         if (status == PRS2_STATUS_TUPLE_CHANGED) {
  320.         /* ----------------
  321.          *  remember, "tuple" is really the slot containing
  322.          *  the tuple.  Once the tuple table stuff works, we
  323.          *  should change the variable names.
  324.          * ----------------
  325.          */
  326.         ExecStoreTuple((Pointer)changedTuple,
  327.                    (Pointer) slot,
  328.                    InvalidBuffer,
  329.                    true);
  330.         }
  331.     } /* if rerel != NULL */
  332.     
  333.     /* ----------------
  334.      *   place the current tuple into the expr context
  335.      * ----------------
  336.      */
  337.     set_ecxt_scantuple(econtext, slot);
  338.     
  339.     /* ----------------
  340.      *  check that the current tuple satisifies the qual-clause
  341.      * ----------------
  342.      */
  343.     qualResult = ExecQual(qual, econtext);
  344.     
  345.     /* ----------------
  346.      *  if our qualification succeeds then we
  347.      *  leave the loop.
  348.      * ----------------
  349.      */
  350.     if (qualResult == true)
  351.         break;
  352.     }
  353.     
  354.     /* ----------------
  355.      *  save the qualifying tuple's tid 
  356.      * ----------------
  357.      */
  358.     oldRelId =             get_ss_OldRelId(scanstate);
  359.     resultRelationInfo =  get_es_result_relation_info(estate);
  360.     
  361.     tuple_tid = (ItemPointer)
  362.     &(((HeapTuple) ExecFetchTuple((Pointer) slot))->t_ctid);
  363.  
  364.     /* ----------------
  365.      *    form a projection tuple, store it in the result tuple
  366.      *  slot and return it.
  367.      * ----------------
  368.      */
  369.     projInfo = get_cs_ProjInfo((CommonState) scanstate);
  370.     
  371.     resultSlot = ExecProject(projInfo, &isDone);
  372.     set_cs_TupFromTlist((CommonState) scanstate, !isDone);
  373.     return resultSlot;
  374. }
  375.